/*
 * @Author: hx 2542123711@QQ.com
 * @Date: 2024-12-03 14:41:36
 * @LastEditors: hx 2542123711@QQ.com
 * @LastEditTime: 2024-12-05 18:39:17
 * @FilePath: /class_thread/mythread.cc
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include <string>
#include <vector>

#define MAX 1024

using namespace std;

int g_val = 10;
// 1.线程创建， 线程等待, 线程终止
// 2.验证全局变量可以被多个线程共享
// 3.线程的健壮性很差，如果说某一个线程发生异常，会导致整个进程接受信号导致整个进程崩溃

// share函数可以被多个执行流同时执行，所以他是被重入的函数
//  void share()
//  {
//      cout << "all thread can see me" << endl;
//  }

// void* show(void* args)
// {
//     const char* name = (char*)args;

//     int cnt = 0;
//     while(true)
//     {
//         printf("%s, newthreadpid:%d, g_val:%d\n", name, getpid(), g_val);
//         // cout << "I am a new thread: " << getpid() << endl;
//         sleep(1);
//         cnt++;
//         if(cnt == 4)
//         {
//             break;
//         }
//     }

//     sleep(1);
//     share();
//     // int a = 10;
//     // a /= 0;

//     return (void*)0;
//     //pthread_exit((void*)2);
//     //注意exit一般适用于进程退出而不是线程退出，如果对该进程的任意一个线程使用exit，会导致整个进程退出
//     //exit(3);
// }

// int main()
// {
//     pthread_t tid;
//     //pthread_create(&tid, nullptr, show, nullptr);
//     pthread_create(&tid, nullptr, show, (void*)"new thread");

//     int cnt = 0;
//     while(true)
//     {
//         printf("I am a thread,pid:%d, g_val:%d, tid:%p\n", getpid(), g_val, tid);
//         // cout << "I am a thread: " << getpid() << "tid: " << tid << endl;
//         sleep(1);

//         cnt++;
//         g_val++;
//         if(cnt == 7)
//         {
//             break;
//         }
//     }

//     void* retval = nullptr;
//     pthread_join(tid, &retval);
//     // printf("new thread quit... quit code:%")
//     cout << "new thread quit..." << "qiut code: " << (pthread_t)retval << endl;

//     sleep(1);
//     share();

//     return 0;
// }

// 4.线程库原生接口函数最后一个参数可以是类对象
//  class Requst
//  {
//  public:
//      Requst(int start, int end, const string& name)
//      :_start(start), _end(end), _name(name)
//      {}

//     int _start;
//     int _end;
//     string _name;
// };

// class Responce
// {
// public:
//     Responce(int result, int exitcode)
//     :_result(result), _exitcode(exitcode)
//     {}

//     int _result;
//     int _exitcode;
// };

// void* ThreadSum(void* args)
// {
//     //把args从void* 转换成Requst*类型
//     Requst* rq = static_cast<Requst*>(args);
//     Responce* rsp = new Responce(0, 0);

//     for(int i=rq->_start; i<=rq->_end; i++)
//     {
//         rsp->_result += i;
//         cout << "ThreadSum: " << i <<endl;
//         usleep(10000);
//     }

//     rsp->_exitcode = 0;

//     printf("%s, sum:%d\n", rq->_name.c_str(), rsp->_result);

//     delete rsp;

//     return (void*)0;
// }

// int main()
// {
//     Requst* rq = new Requst(1, 100, "thread1");

//     pthread_t tid;
//     pthread_create(&tid, nullptr, ThreadSum, rq);

//     void* retval;
//     pthread_join(tid, &retval);

//     delete rq;

//     return 0;
// }

// 5.查看一个线程的tid
//  char* toHex(pthread_t tid)
//  {
//      char buffer[MAX];
//      snprintf(buffer, sizeof(buffer), "%p", tid);

//     return buffer;
// }

// void* threadRoutine(void* args)
// {
//     while(true)
//     {
//         //pthrad_self() ->查看自己的tid
//         cout << "thread id: " << toHex(pthread_self()) << endl;
//         sleep(1);
//     }
// }

// int main()
// {
//     pthread_t tid;
//     pthread_create(&tid, nullptr, threadRoutine, (void*)"thread 1");

//     cout << "In main, thread id is: " << toHex(tid) <<endl;

//     pthread_join(tid, nullptr);

//     return 0;
// }

// 6.创建多个线程相关
// 线程局部变量 线程全局变量 全局变量
//__thread可以用来定义关于线程的全局变量，也叫做线程的局部存储，只能用来定义内置类型
__thread int t_gval = 100;
__thread pid_t id = 0;

class ThreadData
{
public:
    ThreadData(int number)
    {
        _threadname = "thead-" + to_string(number);
    }

public:
    string _threadname;
};

void *threadRoutine(void *args)
{
    ThreadData *thread = static_cast<ThreadData *>(args);

    // 线程内部定义的同名局部变量拥有不同的地址
    // 在线程内部对线程全局变量进行修改只会影响该线程自己的变量，也就是说线程全局变量有自己的独立地址
    // 而一般的全局变量是被所有线程共享的
    int test_i = 0;
    g_val++;
    t_gval++;

    cout << thread->_threadname << ", my pid: " << getpid()
         << ", t_gval: " << t_gval << ", &t_gval: " << &t_gval 
         <<  "g_val: " << g_val << ", &g_val" << &g_val << endl;
 
    // cout << "this thread is: " << thread->_threadname <<", my pid: " <<  getpid()
    // <<"test_i: " << test_i <<", &test_i: " << &test_i <<  endl;
         
    // test_i++;
    // if(test_i == 5)
    // {
    //     break;
    // }

    delete thread;
    return nullptr;
}

int main()
{
    vector<pthread_t> tids;
    for (int i = 1; i <= 4; i++)
    {
        pthread_t tid;

        ThreadData *td = new ThreadData(i);
        pthread_create(&tid, nullptr, threadRoutine, td);
        tids.push_back(tid);
        
    }

    sleep(1);

    // 线程等待 -> 保证主线程最后退出即可
    for (int i = 0; i < tids.size(); i++)
    {
        pthread_join(tids[i], nullptr);
    return 0;
}